/*-------------------------------------------------------------------------
 *
 * buf_ext.h
 *	  Internal definitions for buffer manager ext and the buffer init ext.
 *
 *
 *
 * src/include/storage/buf_ext.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef BUF_EXT_H
#define BUF_EXT_H
#include "postgres.h"
#include "buf_internals.h"
#include "utils/hsearch.h"


// 待确定
#define LWTRANCHE_PCI_BUFFER_CONTENT (8)


#define PCI_PART_LIST_NUM (8)
#define PCI_LRU_LIST_NUM (PCI_PART_LIST_NUM * 2)

#define PCI_INVALID_ID (0)

#define PCI_GET_CTRL_BY_ID(ctx, ctrlId) ((KPHCPciPageCtrl *)(&(ctx->ctrlBuf[(ctrlId) - 1])))
#define PCI_GET_BUCKET_BY_ID(ctx, bckId) ((KPHCPciHashBucket *)(&(ctx->hashtbl.buckets[(bckId) - 1])))
#define PCI_GET_BUCKET_BY_HASH(ctx, hashcode) (PCI_GET_BUCKET_BY_ID(ctx, (((hashcode) % ctx->hashtbl.bucketNum) + 1)))

#define PCI_SET_NO_READ(ctrl) (ctrl->loadStatus = CTRL_PAGE_NO_LOAD)

typedef struct CfsExtentAddress {
    uint32 checksum;
    volatile uint8 nchunks;
    volatile uint8 allocated_chunks;
    uint16 chunknos[FLEXIBLE_ARRAY_MEMBER];
}KPHCCfsExtentAddress;

typedef struct CfsExtentHeader {
    pg_atomic_uint32 nblocks;
    pg_atomic_uint32 allocated_chunks;
    uint16 chunk_size;
    uint8 algorithm : 7;
    uint8 recycleInOrder : 1;
    uint8 recv;
    KPHCCfsExtentAddress cfsExtentAddress[FLEXIBLE_ARRAY_MEMBER];
}KPHCCfsExtentHeader;

typedef struct KPHCExtentLocation {
    int fd;
    RelFileNode relFileNode;
    BlockNumber extentNumber;
    BlockNumber extentStart;
    BlockNumber extentOffset;
    BlockNumber headerNum;
    uint16 chrunkSize;
    uint8 algorithm;
} KPHCExtentLocation;


typedef struct stPciHashBucket {
    LWLock lock;
    uint32 bckId;
    uint32 ctrlCount;
    uint32 firstCtrlId;
} KPHCPciHashBucket;

typedef struct stPciPageHashtbl {
    HashValueFunc hash;
    HashCompareFunc match;
    uint32 bucketNum;
    KPHCPciHashBucket *buckets;
} KPHCPciPageHashtbl;

typedef struct stPciLruList {
    LWLock lock;
    volatile uint32 count;
    volatile uint32 first;
    volatile uint32 last;
} KPHCPciLruList;

typedef struct KPHCCfsBufferKey {
    RelFileNode relFileNode;
    uint32 extentCount;
} KPHCCfsBufferKey;

typedef enum enCtrlState {
    CTRL_STATE_INIT = 0,
    CTRL_STATE_USED = 1, 
    CTRL_STATE_FREE = 2, 
} KPHCCtrlState;

typedef enum enCtrlLoadStatus {
    CTRL_PAGE_NO_LOAD,
    CTRL_PAGE_IS_LOADED,
    CTRL_PAGE_LOADED_ERROR
} KPHCCtrlLoadStatus;

typedef struct __attribute__((aligned(128))) stPciPageCtrl
{
    uint32 ctrlId;
    KPHCCtrlState state;
    volatile uint32 lruPrev;
    volatile uint32 lruNext;
    volatile uint32 bckPrev;
    volatile uint32 bckNext;
    volatile uint32 bckId;

    pg_atomic_uint32 touchNum;
    pg_atomic_uint32 refNum;
    LWLock contentLock;
    KPHCCtrlLoadStatus loadStatus;
    KPHCCfsBufferKey pciKey;
    KPHCCfsExtentHeader *pciPage;
} KPHCPciPageCtrl;

typedef struct __attribute__((aligned(128))) stPciPageBuffCtx
{
    KPHCPciPageCtrl *ctrlBuf;
    char *pageBuf;
    KPHCPciPageHashtbl hashtbl;
    uint32 maxCount;
    KPHCPciLruList mainLru[PCI_PART_LIST_NUM];
    KPHCPciLruList freeLru[PCI_PART_LIST_NUM];
} KPHCPciPageBuffCtx;

typedef enum pciBufferReadMode {
    PCI_BUF_NORMAL_READ,
    PCI_BUF_NO_READ
} KPHCPciBufferReadMode;

extern KPHCPciPageBuffCtx *gPciBufCtx;

void KPHCPciBufInitCtx(void);
extern Size KPHCPciBufferSize(void);

void KPHCPciBufFreePage(KPHCPciPageCtrl *ctrl, const KPHCExtentLocation location, bool need_write);
void KPHCPciLruPushNoLock(KPHCPciLruList *lru, KPHCPciPageCtrl *item, KPHCCtrlState state);

KPHCPciPageCtrl *KPHCPciBufReadPage(const KPHCExtentLocation location, LWLockMode lockMode, KPHCPciBufferReadMode readMode);
typedef KPHCExtentLocation (*KPHCCfsLocationConvert)(SMgrRelation sRel, ForkNumber forknum, BlockNumber logicBlockNumber, bool skipSync, int type);
#endif